home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-23  |  11.9 KB  |  381 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record
  3.  * Copyright (C) 1993 by Charles Sandmann (sandmann@clio.rice.edu)
  4.  * 
  5.  * This file is part of ED.
  6.  * 
  7.  * ED is free software; you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation.
  9.  * 
  10.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  11.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License along with ED
  15.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  16.  * Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18. #include "opsys.h"
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include "memory.h"
  25. #include "ctyp_def.h"
  26. #include "rec.h"
  27. #include "window.h"
  28. #include "ed_def.h"
  29. #include "buffer.h"
  30. #include "buf_def.h"
  31. #include "key_def.h"
  32. #include "mxch_def.h"
  33.  
  34. static Char *ARGV;    /* save argv[0] so we can locate the help file */
  35. static Char multiple;    /* flags that -m is in effect */
  36.  
  37. extern Char *version();
  38. extern Char *filename();
  39.  
  40. /******************************************************************************\
  41. |Routine: main
  42. |Callby: not called
  43. |Purpose: Implements command line interface.
  44. |Arguments:
  45. |    standard unix args:
  46. |       argv[1] is the name of the terminal configuration file.
  47. |       argv[2] is the name of the user's setup file.
  48. |       argv[3] is the number of lines on the terminal screen.
  49. |       argv[4] is the number of columns on the terminal screen.
  50. |       argv[5] is either the first file name or one or more of:
  51. |          -u, which indicates that the position reports should be updated continuously, or
  52. |          -k, which indicates that a backup file should be created when the user EXITs, or
  53. |          -b, which indicates that the files are to be read in as binary files, or
  54. |          -h, which indicates that the files are to be read in as binary files, and only hex displayed, or
  55. |          -z, which indicates that ED is to run a configuration and then exit, or
  56. |          -r[<file>], which indicates that we are recovering edits interactively, or
  57. |          -t[<file>], which indicates that we are text processing, or
  58. |          -f<file>, which means that <file> is a list of file names to edit, or
  59. |          -i<line>, which means position the cursor to line number <line>, or
  60. |          -1, which means to not prompt for additional files (1 pass), or
  61. |          -m, which means to use multiple-file mode, or
  62. |          -n<server>, which calls up the news using <server> as server, or
  63. |          -s<string>, where what follows -s is the search buffer, or
  64. |          -p<string>, where what follows -p is the paste buffer, or
  65. |          -l<string>, where what follows -l is the line buffer, or
  66. |          -w<string>, where what follows -w is the word buffer, or
  67. |          -c<string>, where what follows -c is the char buffer, or
  68. |          -v, reports ED version number and licensing information.
  69. \******************************************************************************/
  70. Int main(argc,argv)
  71. Int argc;
  72. Char **argv;
  73. {
  74.     Char recover,process,diredit,binary,news;
  75.     Char *buffer,editfile[512],recfile[512],bookmark[512];
  76.     Char **p,*q,*r,*s,*filebuf;
  77.     Int i,bookpos,bookbyt,bufferlen;
  78.  
  79.     for(p = argv + 1;(q = *p);p++)
  80.         if(!strcmp(q,"-v"))
  81.         {
  82.             printf("\n\
  83. This is ED version ");
  84.             printf(version());
  85.             printf(" Copyright (C) 1993 Charles Sandmann.\n\
  86. ED comes with ABSOLUTELY NO WARRANTY and is free software distributed\n\
  87. in accordance with the terms of the GNU General Public License Version 2.\n\
  88. \n\
  89. Please use and distribute this program freely, but the source code is covered\n\
  90. by a license that restricts what you may do with it.\n\
  91. \n\
  92. You should have received a file called COPYING with this copy of ED,\n\
  93. which explains the terms of this license in detail. If not, write to:\n\
  94. \n\
  95.       Free Software Foundation\n\
  96.       675 Mass Ave\n\
  97.       Cambridge, MA 02139   USA\n\
  98. \n\
  99. ED was written by Rush Record and is maintained by Charles Sandmann.\n\
  100. Please report all bugs (save the traceback!), enhancement requests, and\n\
  101. requests for the source code to:\n\
  102. \n\
  103.       Charles Sandmann (email: sandmann@clio.rice.edu)\n\
  104.       527 Asheboro\n\
  105.       Katy, TX 77450   USA\n");
  106.             exit(0);
  107.         }
  108.     if(argc < 5)
  109.     {
  110. #ifndef GNUDOS
  111.         printf("\n\
  112. Usage: ED terminal-file startup-file term-rows term-cols [file...]\n\
  113. \n\
  114. If you've never used ED before, you should do the following:\n\
  115. \n\
  116. 1) Determine the name of the directory that holds the ED program. For\n\
  117.    the purposes of this description, we will assume '/usr/local/bin'.\n\
  118. 2) Select one of the terminal files from the directory where the ED\n\
  119.    program resides. If your terminal acts like a VT100, for example,\n\
  120.    use the /usr/local/bin/vt100.ed file for your terminal-file.\n\
  121. 3) Copy the ed.setup file from /usr/local/bin to your home directory.\n\
  122.    Use the name of the new file as startup-file in the command line.\n\
  123. 4) Determine how many rows and columns your terminal (or emulator) has. Use\n\
  124.    the number of rows where term-rows appears and similarly for the columns.\n\
  125. \n\
  126. To start the editor enter:\n\
  127. \n\
  128. /usr/local/bin/ED /usr/local/bin/vt100.ed ~/ed.setup 24 80 file.name\n\
  129. \n\
  130. To get license and version information enter:     /usr/local/bin/ED -v\n\
  131. Good luck!\n\
  132. ");
  133. #else
  134.         printf("\n\
  135. Usage: ED terminal-file startup-file term-rows term-cols [file...]\n\
  136. \n\
  137. If you've never used ED before, you should do the following:\n\
  138. \n\
  139. 1) Determine the name of the directory that holds the ED program. For\n\
  140.    the purposes of this description, we will assume 'C:\\EDC'.\n\
  141. 2) Set up a DOSKEY macro or .BAT file to implement the command using\n\
  142.    PC.ED as the terminal-file and PC.SET as the startup file. The\n\
  143.    term-rows and term-cols can be specified as zero (use current screen\n\
  144.    size) or as values to try and set the size. If you run on a network,\n\
  145.    only the file PC.SET needs to local and writeable.\n\
  146. \n\
  147. DOSKEY example:\n\
  148.    DOSKEY ED=C:\\EDC\\EDC C:\\EDC\\PC.ED C:\\EDC\\PC.SET 50 80 -k -u $*\n\
  149. \n\
  150. BAT file example (contents of ED.BAT):\n\
  151.    C:\\EDC\\EDC C:\\EDC\\PC.ED C:\\EDC\\PC.SET 0 0 -k -u %%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9\n\
  152. \n\
  153. To get license and version information enter:     C:\\EDC\\EDC -v\n\
  154. Good luck!\n\
  155. ");
  156. #endif
  157.         exit(0);
  158.     }
  159.     find_infinity();    /* find the largest Char value, as far as strcmp is concerned */
  160.     recover = process = 0;
  161.     ARGV = argv[0];
  162.     init_terminal(argv[1],argv[2],argv[3],argv[4]);    /* initialize the interface to the terminal */
  163.     if(argc >= 6)
  164.         for(p = argv + 5;(q = *p);p++)
  165.             if(!strcmp(q,"-z"))
  166.                 cfg(argv[1]);    /* never returns */
  167. /* count the args that will need to be quoted */
  168.     for(i = 0,p = argv + 5;(q = *p++);)    /* get total size required */
  169.     {
  170.         if(q[0] != '"' && q[strlen(q) - 1] != '"' && strchr(q,' '))    /* this arg will require quoting, go through the motions to figure the size */
  171.         {
  172.             bookmark[0] = '"';
  173.             for(r = bookmark + 1,i = strlen(q);i--;)
  174.             {
  175.                 if(*q == '"')
  176.                     *r++ = '\\';
  177.                 *r++ = *q++;
  178.             }
  179.             *r++ = '"';
  180.             *r++ = '\0';
  181.             i += strlen(bookmark);
  182.         }
  183.         else
  184.             i += strlen(q) + 1;
  185.     }
  186. /* package the args into a string */
  187.     bufferlen = i + 2;
  188.     if(bufferlen < 1024)
  189.         bufferlen = 1024;
  190.     buffer = (Char *)imalloc(bufferlen);
  191.     for(r = buffer,p = argv + 5;(q = *p++);)
  192.     {
  193.         if(strchr(q,' '))    /* this arg requires quoting */
  194.         {
  195.             bookmark[0] = '"';
  196.             for(s = bookmark + 1,i = strlen(q);i--;)
  197.             {
  198.                 if(*q == '"')
  199.                     *s++ = '\\';
  200.                 *s++ = *q++;
  201.             }
  202.             *s++ = '"';
  203.             *s++ = '\0';
  204.             memcpy(r,bookmark,(i = strlen(bookmark)));
  205.         }
  206.         else
  207.             memcpy(r,q,i = strlen(q));
  208.         r += i;
  209.         *r++ = ' ';
  210.     }
  211.     if(r != buffer)
  212.         r--;
  213.     *r = '\0';
  214.     load_inquire("File",buffer);
  215. /* point to first non-essential argument */
  216.     binary = 0;
  217.     while(parse_filename(buffer,bufferlen,editfile,&recover,recfile,&process,&multiple,&binary,&news))
  218.     {
  219.         CURWINDOW = -1;    /* this is looked at in load_file() to see whether file size may be available */
  220.                         /* edit() sets it to nonnegative */
  221.         set_processmode(process);
  222.         strip_quotes(editfile);
  223.         envir_subs(editfile);
  224.         if(!recover)
  225.             journal_init(editfile);
  226.         BASE = (rec_ptr)imalloc(sizeof(rec_node));
  227.         BASE->length = 0;
  228.         BASE->data = NULL;
  229. #ifndef NO_NEWS
  230.         if(news)
  231.         {
  232.             set_wait_main(0);    /* prevent "Press any key to continue" messages */
  233.             BASE->next = BASE->prev = BASE;
  234.             NETRC = (rec_ptr)imalloc(sizeof(rec_node));
  235.             NETRC->length = 0;
  236.             NETRC->data = NULL;
  237.             NETRC->next = NETRC->prev = NETRC;
  238.             if(!load_news(editfile,BASE,NETRC,bookmark,sizeof(bookmark),news))    /* editfile has the server name, bookmark gets window title */
  239.             {
  240.                 toss_data(NETRC);
  241.                 continue;
  242.             }
  243.             strcpy(editfile,bookmark);
  244.             bookmark[0] = '\0';
  245.             WINDOW[0].filebuf = NULL;
  246.             WINDOW[0].diredit = 0;
  247.             WINDOW[0].binary = 0;
  248.             WINDOW[0].news = 1;    /* this signifies a top-level news window */
  249.         }
  250.         else
  251. #endif
  252.         {
  253.             set_wait_main(0);    /* prevent "Press any key to continue" messages */
  254.             if(load_file(editfile,BASE,bookmark,&bookpos,&bookbyt,&diredit,binary,&filebuf) == -2)
  255.                 continue;
  256.             WINDOW[0].filebuf = filebuf;
  257.             WINDOW[0].diredit = diredit;
  258.             WINDOW[0].binary = binary;
  259.             WINDOW[0].news = 0;
  260.         }
  261.         if(host_in_name(editfile) && diredit)
  262.             dir_store(0,editfile,BASE);
  263.         if((i = strlen(bookmark)))
  264.         {
  265.             WINDOW[0].bookmark = (Char *)imalloc(++i);
  266.             strcpy(WINDOW[0].bookmark,bookmark);
  267.             edit_init_pos(bookpos);
  268.             edit_init_byt(bookbyt);
  269.         }
  270.         set_wait_main(1);    /* enable "Press any key to continue" messages */
  271.         edit(editfile,&multiple,buffer,bufferlen);
  272.         if(WINDOW[0].news)
  273.             toss_data(NETRC);
  274. #ifndef GNUDOS
  275.         for(i = 0;i < NWINDOWS;i++)    /* command() has already done window zero */
  276.             if(WINDOW[i].bookmark)
  277.                 update_bookmark(i);
  278. #endif
  279.         for(i = 0;i < NWINDOWS;i++)    /* toss all memory */
  280.         {
  281.             toss_data(WINDOW[i].base);
  282.             ifree(WINDOW[i].filename);
  283.             if(WINDOW[i].filebuf)
  284.                 unmap_file(WINDOW[i].filebuf);
  285.             if(WINDOW[i].bookmark)
  286.             {
  287.                 ifree(WINDOW[i].bookmark);
  288.                 WINDOW[i].bookmark = NULL;
  289.             }
  290.         }
  291.         if(!recover)
  292.             journal_fini();
  293.         winsub_clean();    /* clean up detached subprocess (VMS only) */
  294.         if(!process)
  295.             recover = 0;
  296.         binary = 0;
  297. /* clean up any remote FTP window data */
  298.         for(i = 0;i < NWINDOWS;i++)
  299.             dir_destroy(i);
  300.         NWINDOWS = 0;
  301.         marge(1,NROW);
  302. #ifndef NO_FTP
  303.         ftp_close();
  304. #endif
  305. #ifndef NO_NEWS
  306.         if(news)
  307.         {
  308.             news_close();
  309.             next();
  310.         }
  311.         news = 0;
  312. #endif
  313.     }
  314.     vtend();
  315.     cleanup(0);
  316.     return(0);
  317. }
  318.  
  319. /******************************************************************************\
  320. |Routine: exefile
  321. |Callby: help
  322. |Purpose: Returns the name of the ed executable, which yields the directory
  323. |         that the help file ought to be in.
  324. |Arguments:
  325. |    none
  326. \******************************************************************************/
  327. Char *exefile()
  328. {
  329.     return(ARGV);
  330. }
  331.  
  332. /******************************************************************************\
  333. |Routine: cancel_multiple
  334. |Callby: command
  335. |Purpose: Ends multiple mode when they issue ABORT command.
  336. |Arguments:
  337. |    none
  338. \******************************************************************************/
  339. void cancel_multiple()
  340. {
  341.     multiple = 0;
  342. }
  343.  
  344. #ifndef GNUDOS
  345. /******************************************************************************\
  346. |Routine: update_bookmark
  347. |Callby: command wincom
  348. |Purpose: Updates a bookmark file for a window.
  349. |Arguments:
  350. |    none
  351. \******************************************************************************/
  352. Int update_bookmark(i)
  353. Int i;
  354. {
  355.     FILE *fp;
  356.     Char buf[512];
  357.     Int record;
  358.     rec_ptr r;
  359.     
  360.     if(WINDOW[i].bookmark)
  361.     {
  362. #ifdef VMS
  363.         if(!(fp = fopen(WINDOW[i].bookmark,"w","ctx=rec","rfm=var","rat=cr","shr=nil","fop=mxv")))
  364. #else
  365.         if(!(fp = fopen(WINDOW[i].bookmark,"w")))
  366. #endif
  367.         {
  368.             sprintf(buf,"Unable to update bookmark file '%s'.",WINDOW[i].bookmark);
  369.             slip_message(buf);
  370.             wait_message();
  371.             return(0);
  372.         }
  373.         for(record = 1,r = WINDOW[i].base->next;r != WINDOW[i].currec;record++,r = r->next);
  374.         fprintf(fp,"%d,%d\n",record,WINDOW[i].curbyt);
  375.         fclose(fp);
  376.     }
  377.     return(1);
  378. }
  379. #endif
  380.  
  381.